/**
    Copyright (c) 2010 yakiimo02
    Distributed under the New BSD License.
    See included license.txt or http://www.yakiimo3d.com/NewBSDLicense.txt
**/

#include "DXUT.h"

#include "SortFragmentsAndRender.h"
#include "DXHelper.h"

/**
*/
SortFragmentsAndRender::SortFragmentsAndRender() : m_pQuadLayout( NULL ), m_pVB( NULL ), m_pVS( NULL ), m_pPS( NULL )
{
}

/**
*/
SortFragmentsAndRender::~SortFragmentsAndRender()
{
}

/**
*/
HRESULT SortFragmentsAndRender::OnCreateDevice( ID3D11Device* pDevice )
{
    HRESULT hr = S_OK;
    ID3DBlob* pBlob = NULL;

    // vertex shader
    V_RETURN( CompileShaderFromFile( L"SortFragmentsAndRender.hlsl", "QuadVS", "vs_4_0", &pBlob ) );
    V_RETURN( pDevice->CreateVertexShader( pBlob->GetBufferPointer(), pBlob->GetBufferSize(), NULL, &m_pVS ) );

    // input layout
    const D3D11_INPUT_ELEMENT_DESC quadlayout[] =
    {
        { "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    };

    V_RETURN( pDevice->CreateInputLayout( quadlayout, 1, pBlob->GetBufferPointer(), pBlob->GetBufferSize(), &m_pQuadLayout ) );
    SAFE_RELEASE( pBlob );    

    // pixel shader
    V_RETURN( CompileShaderFromFile( L"SortFragmentsAndRender.hlsl", "SortFragmentsPS", "ps_5_0", &pBlob ) );
    V_RETURN( pDevice->CreatePixelShader( pBlob->GetBufferPointer(), pBlob->GetBufferSize(), NULL, &m_pPS ) );
    SAFE_RELEASE( pBlob );

    // full screen quad
    SCREEN_VERTEX svQuad[4];
    svQuad[0].pos = D3DXVECTOR4( -1.0f, 1.0f, 0.5f, 1.0f );
    svQuad[1].pos = D3DXVECTOR4( 1.0f, 1.0f, 0.5f, 1.0f );
    svQuad[2].pos = D3DXVECTOR4( -1.0f, -1.0f, 0.5f, 1.0f );
    svQuad[3].pos = D3DXVECTOR4( 1.0f, -1.0f, 0.5f, 1.0f );

    D3D11_BUFFER_DESC vbdesc =
    {
        4 * sizeof( SCREEN_VERTEX ),
        D3D11_USAGE_DEFAULT,
        D3D11_BIND_VERTEX_BUFFER,
        0,
        0
    };
    D3D11_SUBRESOURCE_DATA InitData;
    InitData.pSysMem = svQuad;
    InitData.SysMemPitch = 0;
    InitData.SysMemSlicePitch = 0;
    V_RETURN( pDevice->CreateBuffer( &vbdesc, &InitData, &m_pVB ) );

    return hr;    
}

/**
*/
void SortFragmentsAndRender::OnDestroyDevice()
{
    SAFE_RELEASE( m_pQuadLayout );
    SAFE_RELEASE( m_pVB );
    SAFE_RELEASE( m_pVS );
    SAFE_RELEASE( m_pPS );
}

/**
*/
void SortFragmentsAndRender::OnRender( ID3D11DeviceContext* pD3DContext, ID3D11Device* pDevice, const DXGI_SURFACE_DESC* pBackBufferDesc, 
                                      ID3D11ShaderResourceView* pFragmentLinkSRV, ID3D11ShaderResourceView* pStartOffsetSRV )
{

    // Save the old viewport
    D3D11_VIEWPORT vpOld[D3D11_VIEWPORT_AND_SCISSORRECT_MAX_INDEX];
    UINT nViewPorts = 1;
    pD3DContext->RSGetViewports( &nViewPorts, vpOld );
    
    // Setup the viewport to match the backbuffer
    D3D11_VIEWPORT vp;
    vp.Width = static_cast< float >( pBackBufferDesc->Width );
    vp.Height = static_cast< float >( pBackBufferDesc->Height );
    vp.MinDepth = 0.0f;
    vp.MaxDepth = 1.0f;
    vp.TopLeftX = 0;
    vp.TopLeftY = 0;
    pD3DContext->RSSetViewports( 1, &vp );

    UINT strides = sizeof( SCREEN_VERTEX );
    UINT offsets = 0;
    ID3D11Buffer* pBuffers[1] = { m_pVB };

    pD3DContext->IASetInputLayout( m_pQuadLayout );
    pD3DContext->IASetVertexBuffers( 0, 1, pBuffers, &strides, &offsets );
    pD3DContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP );

    ID3D11ShaderResourceView* aRViews[ 2 ] = { pFragmentLinkSRV, pStartOffsetSRV };
    pD3DContext->PSSetShaderResources( 0, 2, aRViews );

    pD3DContext->VSSetShader( m_pVS, NULL, 0 );
    pD3DContext->PSSetShader( m_pPS, NULL, 0 );
    pD3DContext->Draw( 4, 0 );

    // Restore the Old viewport
    pD3DContext->RSSetViewports( nViewPorts, vpOld );

    //
    ID3D11ShaderResourceView* aRViewsNull[ 2 ] = { NULL, NULL };
    pD3DContext->PSSetShaderResources( 0, 2, aRViewsNull );
    
}